package services

import (
	"fmt"
	"gorm.io/gorm"
	"news/pkg/models"
	"news/pkg/types"
	"news/pkg/types/errors"
	"time"
)

func QueryNews(db *gorm.DB, q string) *gorm.DB {
	return db.Model(&models.News{}).Where("title LIKE ? OR username LIKE ?",
		"%"+q+"%", "%"+q+"%").Order("updated_at")
}

func GetNewsList(db *gorm.DB, q string) *gorm.DB {
	return db.Model(&models.News{}).Where("state", "released").Where("title LIKE ? OR username LIKE ?",
		"%"+q+"%", "%"+q+"%").Order("updated_at")
}
func GetNewsById(db *gorm.DB, id models.Id) (*models.News, error) {
	cond := models.News{}
	cond.Id = id
	return GetNews(db, cond)
}

func DeleteNews(db *gorm.DB, ids []models.Id) error {
	news := models.News{}
	if err := db.Where(ids).Delete(&news).Error; err != nil {
		return err
	}
	return nil
}
func DeleteNewsById(db *gorm.DB, id models.Id) error {
	news := models.News{}
	if err := db.Where("id", id).Delete(&news).Error; err != nil {
		return errors.AutoDbErr(err)
	}
	return nil
}

func AddReadCount(db *gorm.DB, news *models.News) (*models.News, error) {
	news.ReadCount = news.ReadCount + 1
	if err := db.Updates(news).Error; err != nil {
		return nil, errors.AutoDbErr(err)
	}
	return news, nil
}

func GetNews(db *gorm.DB, cond models.News) (*models.News, error) {
	news := models.News{}
	if err := db.Where(cond).First(&news).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, err
		}
		return nil, errors.AutoDbErr(err)
	}
	return &news, nil
}

func CreateNews(db *gorm.DB, form *types.CreateNewsForm) (*models.News, error) {
	news := models.News{
		Title:     form.Title,
		Label:     form.Label,
		NewsImg:   form.NewsImg,
		UserId:    string(form.UserId),
		Username:  form.Username,
		State:     form.State,
		Url:       form.Url,
		Desc:      form.Desc,
		Content:   form.Content,
		ReadCount: 0,
	}
	if err := db.Create(&news).Error; err != nil {
		return nil, errors.AutoDbErr(err)
	}
	return &news, nil
}

func UpdateNews(db *gorm.DB, form *types.UpdateNewsForm) (*models.News, error) {
	news := models.News{}
	if dbErr := db.Model(&news).Where("id", form.Id).Updates(models.News{
		Title:   form.Title,
		Url:     form.Url,
		NewsImg: form.NewsImg,
		Label:   form.Label,
		Desc:    form.Desc,
		Content: form.Content,
		State:   form.State,
	}).Error; dbErr != nil {
		return nil, errors.AutoDbErr(dbErr)
	}
	return GetNewsById(db, form.Id)
}

func UpdateStateByIds(db *gorm.DB, form *types.UpdateStateForm) (interface{}, error) {
	news := models.News{}
	if dbErr := db.Model(&news).Where(form.Ids).Update("state", form.State).Error; dbErr != nil {
		return nil, errors.AutoDbErr(dbErr)
	}
	return nil, nil
}

func GetNewsByUserId(db *gorm.DB, userId models.Id) *gorm.DB {
	return db.Model(&models.News{}).Where("user_id", userId).Order("created_at")
}

func DeleteNewsByUserId(db *gorm.DB, id models.Id) error {
	return db.Where("user_id", id).Delete(&models.News{}).Error
}

func GetNewsByState(db *gorm.DB, state string) *gorm.DB {
	return db.Model(&models.News{}).Where("state", state).Order("created_at")
}

func GetNewsCountByType(db *gorm.DB, timeM bool) (map[string]int, error) {
	counts := []types.GetCountResp{}
	//tx := db
	if timeM {
		currentTime := time.Now()
		oldTime := currentTime.AddDate(0, 0, -7)
		if err := db.Raw("SELECT label,COUNT(1) as num FROM t_news where updated_at "+
			"> ? and t_news.state = 'released' GROUP BY label", oldTime).Scan(&counts).Error; err != nil {
			return nil, errors.AutoDbErr(err)
		}
	} else {
		if err := db.Raw("SELECT label,COUNT(1) as num FROM t_news where t_news.state = 'released' GROUP BY label").Scan(&counts).Error; err != nil {
			return nil, errors.AutoDbErr(err)
		}
	}
	rangemap := map[string]int{
		"military": 0,
		"science":  0,
		"game":     0,
		"pastime":  0,
		"health":   0,
		"car":      0,
	}
	for _, v := range counts {
		rangemap[v.Label] = v.Num
	}
	fmt.Println(rangemap)
	return rangemap, nil
}

func GetDayNewsAddCount(db *gorm.DB, FDay time.Time, SDay time.Time) int {
	var count int
	db.Raw("SELECT COUNT(1) as num FROM t_news where updated_at  between ? and ?", SDay, FDay).Scan(&count)
	return count
}
